using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;

namespace BlackJackSimulator
    {

    public class Game
        {
        private List<Player> m_Player = new List<Player>();
        private List<Deck> m_Deck = new List<Deck>();
        private System.Collections.Hashtable m_RunResult = new System.Collections.Hashtable();
        Random rndDeck = new Random();
        Random rndCard = new Random();
        private int m_DealerWins;
        private int m_DeckCountOriginal;
        public Game()
            {


            }
        public List<Player> GamePlayer
            {
            get
                {
                return m_Player;
                }

            }

        public List<Deck> GameDeck
            {
            get
                {
                return m_Deck;
                }

            }
        public Player AddPlayer()
            {
            Player newPy = new Player();
            newPy.PlayerID = this.GamePlayer.Count + 1;
            this.GamePlayer.Add(newPy);
            return newPy;
            }


        public Deck AddDeck()
            {

            Deck newDk = new Deck();
            newDk.Deck_ID = this.GameDeck.Count + 1;
            newDk.CreateDeck(4,13);
            this.GameDeck.Add(newDk);
            return newDk;

            }
        public System.Collections.Hashtable hshDeckCheck = new System.Collections.Hashtable();
        public bool AddCardToHand(int PyIndex,int HdIndex)
            {
            return AddCardToHand(PyIndex,HdIndex,"");
            }
        public bool AddCardToHand(int PyIndex,int HdIndex,string ActionType)
            {
            bool bnlOk = false;
            rndDeck = new Random();
            rndCard = new Random();
            do
                {
                //which dk to use
                int DkToUse;
                if (m_Deck.Count == 0) { hshDeckCheck.Clear(); CreateDeck(true); }
                DkToUse = rndDeck.Next(0,m_Deck.Count);

                int CdSelectedId;
                CdSelectedId = rndCard.Next(0,m_Deck[DkToUse].Cards.Count);
                if (m_Deck[DkToUse].Cards.Count != 0)
                    {
                    Card cdSelected = m_Deck[DkToUse].Cards[CdSelectedId];
                    cdSelected.DeckID = m_Deck[DkToUse].Deck_ID;
                    cdSelected.ActionType = ActionType;
                    m_Player[PyIndex].PlayerHand[HdIndex].AddCardToHand(cdSelected);
                    
                    hshDeckCheck.Add(cdSelected.DeckID.ToString() + "," + cdSelected.CardID.ToString(),cdSelected.DeckID.ToString() + "," + cdSelected.CardID.ToString());
                    m_Deck[DkToUse].Cards.Remove(cdSelected);
                    bnlOk = true;
                    }
                else
                    {
                    m_Deck.Remove(m_Deck[DkToUse]);

                    }
                } while (!bnlOk);

            return true;
            }

        public bool Clear_Py_PL_Hd()
            {

            foreach (Player vpy in m_Player)
                {
                vpy.NumberofTimesPlayerPlayed = 0;

                }
            return true;
            }
        public DataSets.Results dsResults;

        public PlayerMatrix dsPlayerMatrix = new PlayerMatrix();

        public List<Player> PlayerSummaries = new List<Player>();


        private bool m_StopRuns;
        public bool StopRuns
            {
            get { return m_StopRuns; }
            set { m_StopRuns = value; }
            }

        public void Exec(int NumDK,int NumPym,int NumHd,int NumRes)
            {
            dsPlayerMatrix.SetUp();
            dsResults = new BlackJackSimulator.DataSets.Results();
            m_DeckCountOriginal = NumDK;
            #region Setup number of decks
            CreateDeck(false);
            this.hshDeckCheck.Clear();
            #endregion
            Player Dealer = null;


            for (int iRes = 0; iRes < NumRes; iRes++)
                {
                if (m_StopRuns) { return; }
                #region Exec Runs

                GameProgress(null,null);
                DataSets.Results.GameResultsRow rwResultsRow = dsResults.GameResults.NewGameResultsRow();
                //  rwResultsRow = dtResults.NewResultsRow();
                rwResultsRow.ResultsID = iRes;
                dsResults.GameResults.AddGameResultsRow(rwResultsRow);

                #region AddPlayersToGame
                m_Player.Clear();
                for (int iPlayerCounter = 0; iPlayerCounter < NumPym; iPlayerCounter++)
                    {
                    this.AddPlayer();
                    GamePlayer[iPlayerCounter].CurrentPlayerMatrix = PlayerSummaries[iPlayerCounter].CurrentPlayerMatrix;

                    }
                #endregion
                #region add hands to player
                foreach (Player PlayerToAddHandToo in GamePlayer)
                    {
                    if (!PlayerToAddHandToo.IsPlayerDealer)
                        {
                        for (int iHandAddCounter = 0; iHandAddCounter < NumHd; iHandAddCounter++)
                            {

                            PlayerToAddHandToo.AddHandToPlayer();
                            PlayerToAddHandToo.PlayerHand[iHandAddCounter].HandBetAmount = 5.00;
                            }
                        }
                    else
                        {
                        PlayerToAddHandToo.AddHandToPlayer();
                        Dealer = PlayerToAddHandToo;
                        PlayerSummaries[0].IsPlayerDealer = true;
                        PlayerSummaries[0].PlayerID = 1;

                        }

                    }
                #endregion add hands to player

                #region InitialDeal
                for (int iHandCount = 0; iHandCount < NumHd; iHandCount++)
                    {
                    for (int iCardCount = 0; iCardCount <= 1; iCardCount++)
                        {
                        foreach (Player PlayerToAddHandTo in GamePlayer)
                            {
                                {
                                if (!PlayerToAddHandTo.IsPlayerDealer)
                                    {
                                    this.AddCardToHand(PlayerToAddHandTo.PlayerID - 1,iHandCount);
                                    }
                                }
                            }
                        if (Dealer.PlayerHand[0].CardsInHand.Count < 2)
                            {
                            this.AddCardToHand(Dealer.PlayerID - 1,0);
                            }
                        }
                    }
                #endregion

                #region PlayHand
                foreach (Player GamePlayerPlayingHand in GamePlayer)
                    {
                    if (!GamePlayerPlayingHand.IsPlayerDealer)
                        {
                        foreach (Hand PlayerHand in GamePlayerPlayingHand.PlayerHand)
                            {

                            if (PlayerHand.Is_BlackJack) { break; }
                            string PlayerActionToDo = "";
                            bool bnlContinuePlaying = true;
                            while (bnlContinuePlaying)
                                {
                                //On the intial play check if we have a pair and send over that data to the player matrix
                                string strPlayerHandShows = "";
                                strPlayerHandShows = PlayerHand.HandTotalValue.ToString();
                                if (PlayerHand.CardsInHand.Count == 2)
                                    {
                                    if (PlayerHand.CardsInHand[0].NumberValueOfCard == PlayerHand.CardsInHand[1].NumberValueOfCard)
                                        {
                                        strPlayerHandShows = PlayerHand.CardsInHand[0].NumberValueOfCard + "," + PlayerHand.CardsInHand[1].NumberValueOfCard;
                                        }

                                    }
                                PlayerActionToDo = dsPlayerMatrix.DeterminePlayerAction(Dealer.PlayerHand[0].CardsInHand[0].NumberValueOfCard.ToString(),
                                   strPlayerHandShows,
                                    GamePlayerPlayingHand.CurrentPlayerMatrix);
                                 
                                switch (PlayerActionToDo)
                                    {
                                    case "H":
                                        if (!this.AddCardToHand(GamePlayerPlayingHand.PlayerID - 1,PlayerHand.Hand_ID - 1,PlayerActionToDo))
                                        { bnlContinuePlaying = false; }
                                        if (PlayerHand.HandTotalValue > 21) { bnlContinuePlaying = false; }
                                        break;
                                    case "S":
                                        bnlContinuePlaying = false;
                                        break;
                                    default:
                                        StringBuilder strMessage = new StringBuilder();
                                        strMessage.AppendLine("No settings for ");
                                        strMessage.AppendLine("DealerShows = " + Dealer.PlayerHand[0].CardsInHand[0].NumberValueOfCard.ToString());
                                        strMessage.AppendLine("PlayerShows = " + PlayerHand.HandTotalValue.ToString());
                                        System.Windows.Forms.MessageBox.Show(strMessage.ToString());
                                        break;
                                    }
                                }
                            }
                        }
                    }
                #region PlayDealer
                while (Dealer.PlayerHand[0].HandTotalValue < 17)
                    {
                    if (Dealer.PlayerHand[0].Is_BlackJack) { break; }
                    if (!this.AddCardToHand(Dealer.PlayerID - 1,0)) { break; }
                    }
                #endregion PlayDealer

                #endregion


                foreach (Player ResultPlayer in GamePlayer)
                    {
                    #region DetermineWinForEachPlayer

                    //check hand if player is not the dealer
                    if (!ResultPlayer.IsPlayerDealer)
                        {
                        #region CheckPlayerCards
                        foreach (Hand ResultPlayerHand in ResultPlayer.PlayerHand)
                            {

                            #region CheckPlayersHands
                            int HdVal = ResultPlayerHand.HandTotalValue;
                            int HdVal_DL = Dealer.PlayerHand[0].HandTotalValue;

                            //if dl loses
                            #region
                            if (Dealer.PlayerHand[0].HandBusted)
                                {
                                if (HdVal <= 21 && !ResultPlayerHand.HandBusted)
                                    {
                                    ResultPlayer.IncrementPlayerWins();

                                    ResultPlayerHand.DidHandWin = true;

                                    }
                                else
                                    {
                                    Dealer.IncrementPlayerWins();
                                    Dealer.PlayerHand[0].DidHandWin = true;

                                    }
                                }
                            else
                                {

                                if ((HdVal <= 21) && (HdVal_DL < HdVal))
                                    {
                                    ResultPlayer.IncrementPlayerWins();

                                    ResultPlayerHand.DidHandWin = true;
                                    }
                                else if (HdVal == HdVal_DL)
                                    {
                                    ResultPlayer.IncrementPlayerWins();
                                    ResultPlayerHand.DidHandWin = true;

                                    Dealer.IncrementPlayerWins();
                                    Dealer.PlayerHand[0].DidHandWin = true;

                                    }
                                else
                                    {
                                    Dealer.IncrementPlayerWins();
                                    Dealer.PlayerHand[0].DidHandWin = true;

                                    }
                                }
                            #endregion

                            #endregion CheckPlayersHands
                            }
                        #endregion CheckPlayerCards
                        }

                    //  newRes.AddPlayerToResult(ResultPlayer);

                    #endregion DetermineWinForEachPlayer
                    }

                #region AddResultData


                foreach (Player PlayerDone in GamePlayer)
                    {
                    DataSets.Results.PlayerResultsRow rwPlayerResults = dsResults.PlayerResults.NewPlayerResultsRow();
                    rwPlayerResults.FK_ResultsID = iRes;
                    rwPlayerResults.IS_DEALER = PlayerDone.IsPlayerDealer;
                    rwPlayerResults.PLAYER_ID = PlayerDone.PlayerID;

                    dsResults.PlayerResults.AddPlayerResultsRow(rwPlayerResults);

                    foreach (Hand PlayerHand in PlayerDone.PlayerHand)
                        {
                        DataSets.Results.PlayerHandResultsRow drwDealerHandResults = dsResults.PlayerHandResults.NewPlayerHandResultsRow();
                        drwDealerHandResults.DID_HAND_WIN = PlayerHand.DidHandWin;
                        drwDealerHandResults.FK_PlayerResultsID = rwPlayerResults.PlayerResultsID;
                        drwDealerHandResults.HAND_ID = PlayerHand.Hand_ID;
                        drwDealerHandResults.IS_BLACKJACK = PlayerHand.Is_BlackJack;
                        PlayerSummaries[PlayerDone.PlayerID - 1].TotalBets += PlayerHand.HandBetAmount;
                        if (PlayerHand.DidHandWin)
                            {
                            if (drwDealerHandResults.IS_BLACKJACK)
                                {
                                PlayerSummaries[PlayerDone.PlayerID - 1].TotalWinnings += PlayerHand.HandBetAmount * (1.5);
                                PlayerSummaries[PlayerDone.PlayerID - 1].CountOfBlackjacks += 1;
                                }
                            else
                                {
                                PlayerSummaries[PlayerDone.PlayerID - 1].TotalWinnings += PlayerHand.HandBetAmount;

                                }
                            }
                        drwDealerHandResults.IS_HAND_BUSTED = PlayerHand.HandBusted;
                        drwDealerHandResults.VALUE_OF_HAND = PlayerHand.HandTotalValue;
                        dsResults.PlayerHandResults.AddPlayerHandResultsRow(drwDealerHandResults);
                        if (PlayerHand.DidHandWin && PlayerDone.IsPlayerDealer) { PlayerSummaries[0].IncrementPlayerWins(); m_DealerWins += 1; }
                        if (PlayerHand.DidHandWin && !PlayerDone.IsPlayerDealer) { PlayerSummaries[PlayerDone.PlayerID - 1].IncrementPlayerWins(); }
                        PlayerSummaries[PlayerDone.PlayerID - 1].IncrementNumberOfHandsPlayerPlayed();
                        foreach (Card CardInPlayedHand in PlayerHand.CardsInHand)
                            {
                            DataSets.Results.PlayerResultsCardsInHandRow drwCardsInHand = dsResults.PlayerResultsCardsInHand.NewPlayerResultsCardsInHandRow();
                            drwCardsInHand.CARD_FACE_VALUE = CardInPlayedHand.GetNumberValueOfCD(CardInPlayedHand.CardValue);
                            drwCardsInHand.CARD_ID = CardInPlayedHand.CardID;
                            drwCardsInHand.CARD_SUIT = CardInPlayedHand.cardSuitType.ToString();
                            drwCardsInHand.CARD_VALUE = CardInPlayedHand.NumberValueOfCard;
                            drwCardsInHand.DECK_ID = CardInPlayedHand.DeckID;
                            drwCardsInHand.PLAYED_ACTION = CardInPlayedHand.ActionType;
                            DeckIDUsed(drwCardsInHand.DECK_ID,null);
                            drwCardsInHand.FK_PlayerHandResultsID = drwDealerHandResults.PlayerHandResultsID;
                            dsResults.PlayerResultsCardsInHand.AddPlayerResultsCardsInHandRow(drwCardsInHand);
                            }
                        }
                    }


                #endregion AddDataForDealer

                #endregion Exec Runs
                }


            }

        private void CreateDeck(bool ReShuffle)
            {
            for (int iDeckCounter = 0; iDeckCounter < m_DeckCountOriginal; iDeckCounter++)
                {
                this.AddDeck();
                }
            if (ReShuffle)
                {
                foreach (Player ShufflePlayer in GamePlayer)
                    {
                    foreach (Hand ShufflePlayerHand in ShufflePlayer.PlayerHand)
                        {
                        foreach (Card ShufflePlayerHandCard in ShufflePlayerHand.CardsInHand)
                            {

                            foreach (Card SelectedCard in m_Deck[ShufflePlayerHandCard.DeckID - 1].Cards)
                                {
                                if ((SelectedCard.cardSuitType==ShufflePlayerHandCard.cardSuitType) 
                                    && (SelectedCard.CardValue==ShufflePlayerHandCard.CardValue))
                                    {
                                    m_Deck[ShufflePlayerHandCard.DeckID - 1].Cards.Remove(SelectedCard);
                                    hshDeckCheck.Add(ShufflePlayerHandCard.DeckID.ToString() + "," + ShufflePlayerHandCard.CardID.ToString(),ShufflePlayerHandCard.DeckID.ToString() + "," + ShufflePlayerHandCard.CardID.ToString());
                                    break;
                                    }
                                }
                            
                            }
                        }
                    }
                }

            DecksReset(null,null);
            }

 

        public event EventHandler GameProgress;
        public event EventHandler DeckIDUsed;
        public event EventHandler DecksReset;
        }


    }
